//------------------------------------------------------------------------------
// The contents of this file are subject to the nopCommerce Public License Version 1.0 ("License"); you may not use this file except in compliance with the License.
// You may obtain a copy of the License at  http://www.nopCommerce.com/License.aspx. 
// 
// Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. 
// See the License for the specific language governing rights and limitations under the License.
// 
// The Original Code is nopCommerce.
// The Initial Developer of the Original Code is NopSolutions.
// All Rights Reserved.
// 
// Contributor(s): _______. 
//------------------------------------------------------------------------------

using System;
using System.Globalization;
using System.Text;
using System.Web.UI.WebControls;
using NopSolutions.NopCommerce.BusinessLogic;
using NopSolutions.NopCommerce.BusinessLogic.Model;
using NopSolutions.NopCommerce.BusinessLogic.Utils;
using NopSolutions.NopCommerce.Controls;

namespace NopSolutions.NopCommerce.Web.Modules
{
    public partial class ProductAttributesControl : BaseNopFrontendUserControl
    {
        //private int _productVariantId = 0;
        //private bool _hidePrices = false;

        protected override void OnLoad(EventArgs e) {
            base.OnLoad(e);

            CreateAttributeControls();
        }

        public void CreateAttributeControls() {
            var productVariant = this.ProductService.GetProductVariantById(this.ProductVariantId);
            if (productVariant != null) {
                this.phAttributes.Controls.Clear();
                var productVariantAttributes = productVariant.ProductVariantAttributes;
                if (productVariantAttributes.Count > 0) {
                    StringBuilder adjustmentTableScripts = new StringBuilder();
                    StringBuilder attributeScripts = new StringBuilder();

                    this.Visible = true;
                    foreach (var attribute in productVariantAttributes) {

                        // editor
                        var editorDiv = new Panel();
                        editorDiv.CssClass = "control-group";

                        // label
                        var attributeLabel = new Label();
                        attributeLabel.CssClass = "control-label";

                        // help note
                        //HtmlGenericControl helpNote = new HtmlGenericControl("p");
                        //helpNote.Attributes.Add("class", "help-block");

                        //text prompt / title
                        string textPrompt = string.Empty;
                        if (!string.IsNullOrEmpty(attribute.TextPrompt))
                            textPrompt = attribute.TextPrompt;
                        else
                            textPrompt = attribute.ProductAttribute.LocalizedName;

                        attributeLabel.Text += Server.HtmlEncode(textPrompt);

                        if (attribute.IsRequired)
                            attributeLabel.Text += "<span class=\"required\">*</span> ";

                        //description
                        if (!string.IsNullOrEmpty(attribute.ProductAttribute.LocalizedDescription))
                            attributeLabel.ToolTip = Server.HtmlEncode(attribute.ProductAttribute.LocalizedDescription);

                        //bool addBreak = true;
                        //switch (attribute.AttributeControlType) {
                        //    case AttributeControlTypeEnum.TextBox: {
                        //            addBreak = false;
                        //        }
                        //        break;
                        //    default:
                        //        break;
                        //}
                        //if (addBreak) {
                        //    attributeTitle.Text += "<br />";
                        //}
                        //else {
                        //    attributeTitle.Text += "&nbsp;&nbsp;&nbsp;";
                        //}

                        editorDiv.Controls.Add(attributeLabel);
                        phAttributes.Controls.Add(editorDiv);

                        var editorControlsDiv = new Panel();
                        editorControlsDiv.CssClass = "controls";

                        string controlId = string.Format("{0}_{1}", attribute.ProductAttribute.ProductAttributeId, attribute.ProductVariantAttributeId);
                        switch (attribute.AttributeControlType) {
                            case AttributeControlTypeEnum.DropdownList: {
                                    var ddlAttributes = new DropDownList();
                                    ddlAttributes.Attributes.Add("class", "input-medium");
                                    attributeLabel.AssociatedControlID = ddlAttributes.ID = controlId;

                                    editorControlsDiv.Controls.Add(ddlAttributes);

                                    ddlAttributes.Items.Clear();

                                    //dynamic price update
                                    if (this.SettingManager.GetSettingValueBoolean("ProductAttribute.EnableDynamicPriceUpdate")) {
                                        adjustmentTableScripts.AppendFormat("{0}['{1}'] = new Array(", AdjustmentTableName, ddlAttributes.ClientID);
                                        attributeScripts.AppendFormat("$('#{0}').change(function(){{{1}();}});\n", ddlAttributes.ClientID, AdjustmentFuncName);
                                    }

                                    int numberOfJsArrayItems = 0;
                                    if (!attribute.IsRequired) {
                                        ddlAttributes.Items.Add(new ListItem("---", "0"));

                                        //dynamic price update
                                        if (this.SettingManager.GetSettingValueBoolean("ProductAttribute.EnableDynamicPriceUpdate")) {
                                            adjustmentTableScripts.AppendFormat(CultureInfo.InvariantCulture, "{0},", decimal.Zero);
                                            numberOfJsArrayItems++;
                                        }
                                    }
                                    var pvaValues = attribute.ProductVariantAttributeValues;

                                    //values
                                    bool preSelectedSet = false;
                                    foreach (var pvaValue in pvaValues) {
                                        string pvaValueName = pvaValue.LocalizedName;

                                        //display price if allowed
                                        if (!this.HidePrices &&
                                            (!this.SettingManager.GetSettingValueBoolean("Common.HidePricesForNonRegistered") ||
                                            (NopContext.Current.User != null &&
                                            !NopContext.Current.User.IsGuest))) {
                                            // should we display the adjustment?
                                            if (pvaValue.DisplayAdjustment) {
                                                decimal taxRate = decimal.Zero;
                                                decimal priceAdjustmentBase = this.TaxService.GetPrice(productVariant, pvaValue.PriceAdjustment, out taxRate);
                                                decimal priceAdjustment = this.CurrencyService.ConvertCurrency(priceAdjustmentBase, this.CurrencyService.PrimaryStoreCurrency, NopContext.Current.WorkingCurrency);

                                                if (priceAdjustmentBase > decimal.Zero) {
                                                    pvaValueName += string.Format(" [+{0}]", PriceHelper.FormatPrice(priceAdjustment, false, false));
                                                }
                                                else if (priceAdjustmentBase < decimal.Zero) {
                                                    pvaValueName += string.Format(" [-{0}]", PriceHelper.FormatPrice(-priceAdjustment, false, false));
                                                }

                                                //dynamic price update
                                                if (this.SettingManager.GetSettingValueBoolean("ProductAttribute.EnableDynamicPriceUpdate")) {
                                                    adjustmentTableScripts.AppendFormat(CultureInfo.InvariantCulture, "{0},", (float)priceAdjustment);
                                                    numberOfJsArrayItems++;
                                                }
                                            }
                                        }

                                        var pvaValueItem = new ListItem(pvaValueName, pvaValue.ProductVariantAttributeValueId.ToString());
                                        if (!preSelectedSet && pvaValue.IsPreSelected) {
                                            pvaValueItem.Selected = pvaValue.IsPreSelected;
                                            preSelectedSet = true;
                                        }
                                        ddlAttributes.Items.Add(pvaValueItem);
                                    }

                                    //dynamic price update
                                    if (this.SettingManager.GetSettingValueBoolean("ProductAttribute.EnableDynamicPriceUpdate")) {
                                        //If you create an array with a single numeric parameter, that number is used for specifying the number of elements in this array.
                                        //so have a little hack here (we need at least two elements)
                                        if (numberOfJsArrayItems == 1) {
                                            adjustmentTableScripts.AppendFormat(CultureInfo.InvariantCulture, "{0},", decimal.Zero);
                                        }
                                    }

                                    //dynamic price update
                                    if (this.SettingManager.GetSettingValueBoolean("ProductAttribute.EnableDynamicPriceUpdate")) {
                                        adjustmentTableScripts.Length -= 1;
                                        adjustmentTableScripts.Append(");\n");
                                    }
                                }
                                break;
                            case AttributeControlTypeEnum.RadioList: {
                                    var rblAttributes = new RadioButtonList();
                                    attributeLabel.AssociatedControlID = rblAttributes.ID = controlId;

                                    editorControlsDiv.Controls.Add(rblAttributes);

                                    rblAttributes.Items.Clear();

                                    var pvaValues = attribute.ProductVariantAttributeValues;
                                    bool preSelectedSet = false;
                                    foreach (var pvaValue in pvaValues) {
                                        string pvaValueName = pvaValue.LocalizedName;

                                        //display price if allowed
                                        if (!this.HidePrices &&
                                            (!this.SettingManager.GetSettingValueBoolean("Common.HidePricesForNonRegistered") ||
                                            (NopContext.Current.User != null &&
                                            !NopContext.Current.User.IsGuest))) {
                                            // should we display the adjustment?
                                            if (pvaValue.DisplayAdjustment) {
                                                decimal taxRate = decimal.Zero;
                                                decimal priceAdjustmentBase = this.TaxService.GetPrice(productVariant, pvaValue.PriceAdjustment, out taxRate);
                                                decimal priceAdjustment = this.CurrencyService.ConvertCurrency(priceAdjustmentBase, this.CurrencyService.PrimaryStoreCurrency, NopContext.Current.WorkingCurrency);
                                                if (priceAdjustmentBase > decimal.Zero) {
                                                    pvaValueName += string.Format(" [+{0}]", PriceHelper.FormatPrice(priceAdjustment, false, false));
                                                }
                                                else if (priceAdjustmentBase < decimal.Zero) {
                                                    pvaValueName += string.Format(" [-{0}]", PriceHelper.FormatPrice(-priceAdjustment, false, false));
                                                }

                                                //dynamic price update
                                                if (this.SettingManager.GetSettingValueBoolean("ProductAttribute.EnableDynamicPriceUpdate")) {
                                                    adjustmentTableScripts.AppendFormat(CultureInfo.InvariantCulture, "{0}['{1}_{2}'] = {3};\n", AdjustmentTableName, rblAttributes.ClientID, rblAttributes.Items.Count, (float)priceAdjustment);
                                                    attributeScripts.AppendFormat("$('#{0}_{1}').click(function(){{{2}();}});\n", rblAttributes.ClientID, rblAttributes.Items.Count, AdjustmentFuncName);
                                                }
                                            }
                                        }

                                        var pvaValueItem = new ListItem(Server.HtmlEncode(pvaValueName), pvaValue.ProductVariantAttributeValueId.ToString());
                                        if (!preSelectedSet && pvaValue.IsPreSelected) {
                                            pvaValueItem.Selected = pvaValue.IsPreSelected;
                                            preSelectedSet = true;
                                        }
                                        rblAttributes.Items.Add(pvaValueItem);
                                    }
                                }
                                break;
                            case AttributeControlTypeEnum.Checkboxes: {
                                    var cblAttributes = new CheckBoxList();
                                    attributeLabel.AssociatedControlID = cblAttributes.ID = controlId;

                                    editorControlsDiv.Controls.Add(cblAttributes);

                                    cblAttributes.Items.Clear();

                                    //values
                                    var pvaValues = attribute.ProductVariantAttributeValues;
                                    foreach (var pvaValue in pvaValues) {
                                        string pvaValueName = pvaValue.LocalizedName;

                                        //display price if allowed
                                        if (!this.HidePrices &&
                                            (!this.SettingManager.GetSettingValueBoolean("Common.HidePricesForNonRegistered") ||
                                            (NopContext.Current.User != null &&
                                            !NopContext.Current.User.IsGuest))) {

                                            // should we display the adjustment?
                                            if (pvaValue.DisplayAdjustment) {
                                                decimal taxRate = decimal.Zero;
                                                decimal priceAdjustmentBase = this.TaxService.GetPrice(productVariant, pvaValue.PriceAdjustment, out taxRate);
                                                decimal priceAdjustment = this.CurrencyService.ConvertCurrency(priceAdjustmentBase, this.CurrencyService.PrimaryStoreCurrency, NopContext.Current.WorkingCurrency);
                                                if (priceAdjustmentBase > decimal.Zero) {
                                                    pvaValueName += string.Format(" [+{0}]", PriceHelper.FormatPrice(priceAdjustment, false, false));
                                                }
                                                else if (priceAdjustmentBase < decimal.Zero) {
                                                    pvaValueName += string.Format(" [-{0}]", PriceHelper.FormatPrice(-priceAdjustment, false, false));
                                                }

                                                //dynamic price update
                                                if (this.SettingManager.GetSettingValueBoolean("ProductAttribute.EnableDynamicPriceUpdate")) {
                                                    adjustmentTableScripts.AppendFormat(CultureInfo.InvariantCulture, "{0}['{1}_{2}'] = {3};\n", AdjustmentTableName, cblAttributes.ClientID, cblAttributes.Items.Count, (float)priceAdjustment);
                                                    attributeScripts.AppendFormat("$('#{0}_{1}').click(function(){{{2}();}});\n", cblAttributes.ClientID, cblAttributes.Items.Count, AdjustmentFuncName);
                                                }
                                            }
                                        }

                                        var pvaValueItem = new ListItem(Server.HtmlEncode(pvaValueName), pvaValue.ProductVariantAttributeValueId.ToString());
                                        pvaValueItem.Selected = pvaValue.IsPreSelected;
                                        cblAttributes.Items.Add(pvaValueItem);
                                    }
                                }
                                break;
                            case AttributeControlTypeEnum.TextBox: {
                                    var txtAttribute = new TextBox();
                                    txtAttribute.Attributes.Add("class", "input-medium");
                                    txtAttribute.Width = this.SettingManager.GetSettingValueInteger("ProductAttribute.Textbox.Width", 300);
                                    attributeLabel.AssociatedControlID = txtAttribute.ID = controlId;

                                    editorControlsDiv.Controls.Add(txtAttribute);
                                }
                                break;
                            case AttributeControlTypeEnum.MultilineTextbox: {
                                    var txtAttribute = new TextBox();
                                    txtAttribute.Attributes.Add("class", "input-medium");
                                    attributeLabel.AssociatedControlID = txtAttribute.ID = controlId;
                                    txtAttribute.TextMode = TextBoxMode.MultiLine;
                                    txtAttribute.Width = this.SettingManager.GetSettingValueInteger("ProductAttribute.MultiTextbox.Width", 300);
                                    txtAttribute.Height = this.SettingManager.GetSettingValueInteger("ProductAttribute.MultiTextbox.Height", 150);

                                    editorControlsDiv.Controls.Add(txtAttribute);
                                }
                                break;
                            case AttributeControlTypeEnum.Datepicker: {
                                    var datePicker = new NopDatePicker();
                                    datePicker.CssClass = "input-medium";
                                    //changes these properties in order to change year range
                                    datePicker.FirstYear = DateTime.Now.Year;
                                    datePicker.LastYear = DateTime.Now.Year + 1;
                                    attributeLabel.AssociatedControlID = datePicker.ID = controlId;

                                    editorControlsDiv.Controls.Add(datePicker);
                                }
                                break;
                            default:
                                break;
                        }

                        //editorControlsDiv.Controls.Add(helpNote);
                        editorDiv.Controls.Add(editorControlsDiv);
                    }


                    //display price if allowed
                    if (!this.HidePrices &&
                        (!this.SettingManager.GetSettingValueBoolean("Common.HidePricesForNonRegistered") ||
                        (NopContext.Current.User != null &&
                        !NopContext.Current.User.IsGuest))) {
                        //dynamic price update
                        if (this.SettingManager.GetSettingValueBoolean("ProductAttribute.EnableDynamicPriceUpdate")) {
                            lblAdjustmentTableScripts.Text = adjustmentTableScripts.ToString();
                            lblAttributeScripts.Text = attributeScripts.ToString();
                            phDynPrice.Visible = true;
                        }
                        else {
                            phDynPrice.Visible = false;
                        }
                    }
                    else {
                        phDynPrice.Visible = false;
                    }
                }
                else {
                    this.Visible = false;
                }
            }
            else {
                this.Visible = false;
            }
        }

        public string SelectedAttributes {
            get {
                string selectedAttributes = string.Empty;
                var productVariantAttributes = this.ProductAttributeService.GetProductVariantAttributesByProductVariantId(this.ProductVariantId);
                foreach (ProductVariantAttribute attribute in productVariantAttributes) {
                    string controlId = string.Format("{0}_{1}", attribute.ProductAttribute.ProductAttributeId, attribute.ProductVariantAttributeId);
                    switch (attribute.AttributeControlType) {
                        case AttributeControlTypeEnum.DropdownList: {
                                var ddlAttributes = phAttributes.FindControl(controlId) as DropDownList;
                                if (ddlAttributes != null) {
                                    int selectedAttributeId = 0;
                                    if (!String.IsNullOrEmpty(ddlAttributes.SelectedValue)) {
                                        selectedAttributeId = int.Parse(ddlAttributes.SelectedValue);
                                    }
                                    if (selectedAttributeId > 0) {
                                        selectedAttributes = ProductAttributeHelper.AddProductAttribute(selectedAttributes,
                                            attribute, selectedAttributeId.ToString());
                                    }
                                }
                            }
                            break;
                        case AttributeControlTypeEnum.RadioList: {
                                var rblAttributes =
                                    phAttributes.FindControl(controlId) as RadioButtonList;
                                if (rblAttributes != null) {
                                    int selectedAttributeId = 0;
                                    if (!String.IsNullOrEmpty(rblAttributes.SelectedValue)) {
                                        selectedAttributeId = int.Parse(rblAttributes.SelectedValue);
                                    }
                                    if (selectedAttributeId > 0) {
                                        selectedAttributes = ProductAttributeHelper.AddProductAttribute(selectedAttributes,
                                            attribute, selectedAttributeId.ToString());
                                    }
                                }
                            }
                            break;
                        case AttributeControlTypeEnum.Checkboxes: {
                                var cblAttributes = phAttributes.FindControl(controlId) as CheckBoxList;
                                if (cblAttributes != null) {
                                    foreach (ListItem item in cblAttributes.Items) {
                                        if (item.Selected) {
                                            int selectedAttributeId = 0;
                                            if (!String.IsNullOrEmpty(item.Value)) {
                                                selectedAttributeId = int.Parse(item.Value);
                                            }
                                            if (selectedAttributeId > 0) {
                                                selectedAttributes = ProductAttributeHelper.AddProductAttribute(selectedAttributes,
                                                    attribute, selectedAttributeId.ToString());
                                            }
                                        }
                                    }
                                }
                            }
                            break;
                        case AttributeControlTypeEnum.TextBox: {
                                var txtAttribute = phAttributes.FindControl(controlId) as TextBox;
                                if (txtAttribute != null) {
                                    string enteredText = txtAttribute.Text.Trim();
                                    if (!String.IsNullOrEmpty(enteredText)) {
                                        selectedAttributes = ProductAttributeHelper.AddProductAttribute(selectedAttributes,
                                            attribute, enteredText);
                                    }
                                }
                            }
                            break;
                        case AttributeControlTypeEnum.MultilineTextbox: {
                                var txtAttribute = phAttributes.FindControl(controlId) as TextBox;
                                if (txtAttribute != null) {
                                    string enteredText = txtAttribute.Text.Trim();
                                    if (!String.IsNullOrEmpty(enteredText)) {
                                        selectedAttributes = ProductAttributeHelper.AddProductAttribute(selectedAttributes,
                                            attribute, enteredText);
                                    }
                                }
                            }
                            break;
                        case AttributeControlTypeEnum.Datepicker: {
                                var datePicker = phAttributes.FindControl(controlId) as NopDatePicker;
                                if (datePicker != null) {
                                    DateTime? selectedDate = datePicker.SelectedDate;
                                    if (selectedDate.HasValue) {
                                        selectedAttributes = ProductAttributeHelper.AddProductAttribute(selectedAttributes,
                                            attribute, selectedDate.Value.ToString("D"));
                                    }
                                }
                            }
                            break;
                        default:
                            break;
                    }
                }
                return selectedAttributes;
            }
        }

        public int ProductVariantId {
            //get { return _productVariantId; }
            //set { _productVariantId = value; }
            get {
                if (ViewState["ProductVariantId"] == null)
                    return 0;
                else
                    return (int)ViewState["ProductVariantId"];
            }
            set {
                ViewState["ProductVariantId"] = value;
            }
        }

        public string AdjustmentTableName {
            get {
                return String.Format("adjustmentTable_{0}", ProductVariantId);
            }
        }

        public string AdjustmentFuncName {
            get {
                return String.Format("adjustPrice_{0}", ProductVariantId);
            }
        }

        public string PriceVarName {
            get {
                return String.Format("priceValForDynUpd_{0}", ProductVariantId);
            }
        }

        public string PriceVarClass {
            get {
                return String.Format("price-val-for-dyn-upd-{0}", ProductVariantId);
            }
        }

        public bool HidePrices {
            //get { return _hidePrices; }
            //set { _hidePrices = value; }
            get {
                if (ViewState["HidePrices"] == null)
                    return false;
                else
                    return (bool)ViewState["HidePrices"];
            }
            set {
                ViewState["HidePrices"] = value;
            }
        }
    }
}